/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "frm_control_TButton.h"
using namespace frm;
using namespace control;

// TStyle /////////////////////////////////////////////////////////////////////

//
void TButton::TStyle::SetDefault()
{
  Normal.Cursor.Set(cursor::TCursorWin(IDC_ARROW));
  Normal.Filler.Set(filler::TRoundRect(grf::TColor(255,255,255),grf::TColor(0,0,255)));

  Down.Cursor.Set(cursor::TCursorWin(IDC_ARROW));
  Down.Filler.Set(filler::TRoundRect(grf::TColor(255,255,255),grf::TColor(255,255,0)));

  Flat.Cursor.Set(cursor::TCursorWin(IDC_ARROW));
  Flat.Filler.Set(filler::TRoundRect(grf::TColor(255,255,255),grf::TColor(255,0,0)));

  Disable.Cursor.Set(cursor::TCursorWin(IDC_ARROW));
  Disable.Filler.Set(filler::TColor(128,128,128));

  EnTimer = false;
}

//
void TButton::TStyle::SetFromParent(frm::TStyle *Parent_)
{
  if (!Parent_) {
    return;
  }

  TStyle *Parent = dynamic_cast<TStyle*>(Parent_);
  
  Normal.Filler.SetFromParent(Parent->Normal.Filler);
  Normal.Cursor.SetFromParent(Parent->Normal.Cursor);
  Normal.Border.SetFromParent(Parent->Normal.Border);

  Down.Filler.SetFromParent(Parent->Down.Filler);
  Down.Cursor.SetFromParent(Parent->Down.Cursor);
  Down.Border.SetFromParent(Parent->Down.Border);

  Flat.Filler.SetFromParent(Parent->Flat.Filler);
  Flat.Cursor.SetFromParent(Parent->Flat.Cursor);
  Flat.Border.SetFromParent(Parent->Flat.Border);

  Disable.Filler.SetFromParent(Parent->Disable.Filler);
  Disable.Cursor.SetFromParent(Parent->Disable.Cursor);
  Disable.Border.SetFromParent(Parent->Disable.Border);

  EnTimer = false;
}

//
svl::TInfoParam TButton::TStyle::AddInfoTo(svl::TInfoParam Info)
{
  return frm::TStyle::AddInfoTo(Info)
   .Add("Normal" ,Normal)
   .Add("Down"   ,Down)
   .Add("Flat"   ,Flat)
   .Add("Disable",Disable)
   .Add("EnTimer",EnTimer)
  ;
}

// TButton ////////////////////////////////////////////////////////////////////

//
TButton::TButton(TWindow &Window) : TPanel(Window),Events(*this)//,TimerS(this)
{
  struct TStyle : public TButton::TStyle
  {
    TStyle() { SetDefault(); }
  };
  static TStyle Style; 
  SetStyle(Style);

  down = false;
  timerActive = false;
  Timer = NULL;
  SetEnable(); 
  SetKeepDown();
  
  Width_Fixed(100).Height_Fixed(50)
   .DirectChildren_Horz()
   .WAlignChildren_Begin().HAlignChildren_Begin();
}

//
TButton &TButton::SetStyle(TStyle &V)
{
  style = &V; 
  TPanel::SetStyle(V.Normal);
  enTimer = V.EnTimer;
  return *this;
}

//
void TButton::UpdateEnable(bool V)
{
  if (enable != V) {
    enable = V; 
    
    if (enable) {
      if (GetMouse().GetEnter() == this) { 
        TPanel::UpdateStyle(style->Flat);
      }
      else { 
        TPanel::UpdateStyle(style->Normal);
      }
    }
    else { 
      TPanel::UpdateStyle(style->Disable);
    }
  }
}

//
void TButton::UpdateDown(bool V)
{
  if (V == down) { 
    return;
  }
  
  Events.Get().TEvents_BeforeChangeDown(TEvents::TI(Events),*this,down,V);
  
  if (V == down) { 
    return;
  }

  if (V && enable && !down) {
    down = true; 
    TPanel::UpdateStyle(style->Down);
    Events.Get().TEvents_AfterDown(TEvents::TI(Events),*this);
    
	if( enTimer ){
		Timer = new TButtonTimer( this, 700, 100);
		timerActive = true;
	}
	
	//Events.Click(TEvents::TClick(Events));
  }
  else if (enable && down) {
    down = false; 
    TPanel::UpdateStyle(style->Normal);
  }
}
                
//
void TButton::TComponent_Mouse(TMouse Mouse)
{
	if (enable) switch (Mouse.State) {
  
    case grf::TMouse::EState_Move: {
		TGeometryRect GRect; 
		GetWindow().CalcGeometryRect( this, GRect ); 
		if( down ){
		  if( !GRect.RThis.IsContain( Mouse.PtClient ) ){
		    TPanel::UpdateStyle(style->Normal);
		    delete Timer; Timer = NULL;
		  }
		  else{
		    TPanel::UpdateStyle(style->Down);
			if( timerActive && Timer == NULL) 
				Timer = new TButtonTimer(this, 0, 100);
		  }
		}
    }
    break;
    
    case grf::TMouse::EState_LButtonDown:
    case grf::TMouse::EState_LButtonDblClick: {
      if (!keepDown && !down) { 
        Mouse_SetCapture(); 
        UpdateDown(true);
      }
      else { 
        UpdateDown(!down);
      }
    }
    break;
	
	  case grf::TMouse::EState_LButtonUp: {
      if (!keepDown && down) { 
	      TGeometryRect GRect; 
		    GetWindow().CalcGeometryRect( this, GRect ); 
		  
		    Mouse_ReleaseCapture();
		    UpdateDown(false);
		  
		    delete Timer; Timer=NULL; timerActive = false;
		  
		    if( GRect.RThis.IsContain( Mouse.PtClient ) ){
		      Events.Click(TEvents::TClick(Events));
		      Click();
		      TPanel::UpdateStyle(style->Flat);
		    }
	    }
    }
    break;
  }

  TPanel::TComponent_Mouse(Mouse);
}

//
void TButton::TComponent_MouseEnter()
{
  TPanel::TComponent_MouseEnter(); 

  if (enable && !down) { 
    TPanel::UpdateStyle(style->Flat);
  }
}

//
void TButton::TComponent_MouseExit()
{
  TPanel::TComponent_MouseExit(); 
  if (enable) { 
    if (down) { 
      TPanel::UpdateStyle(style->Down);
    }
    else { 
      TPanel::UpdateStyle(style->Normal);
    }
  }
}

//
void TButton::TComponent_InheritStyleFrom(TTableOfStyles &ParentStyles)
{ 
  TStyle *Style = dynamic_cast<TStyle*>(ParentStyles.SearchByEqualType(TStyle::TType())); if (Style) {
    SetStyle(*Style);
  }
}


void TButton::TEventsList::Click(frm::control::TButton::TEvents::TClick &Param){
	Get().TEvents_Click(Param);
}

////////////////////////////////////////////////////////////////
TButton::TButtonTimer::TButtonTimer(frm::control::TButton* button, DWORD _start, DWORD _period)
: Button(button)
, svl::TTimer(_start,_period)
{
}

void TButton::TButtonTimer::TTimer_Tick(){
	Button->Events.Get().TEvents_AfterDown(TButton::TEvents::TI(Button->Events),*Button);
	Button->Click();
}

